#include "hplczkysparsecommonpacket.h"
#include "hplczkyspfcid.h"
#include "hplczkyspacketformat.h"
#include "hplczkysprotocolcommondata.h"
#include "hplczkysparsecommonsystempacket.h"
#include "hplczkyscheckpacket.h"

#include <QDebug>
#include "modulehplccmdid.h"

namespace hplc
{
namespace zkys
{

HplcZkysParseCommonPacket::HplcZkysParseCommonPacket(HplcZkysProtocolCommonData &data, hplc::CommonParam &param, QObject *parent)
    : BaseParsePacket (data, parent)
    , m_param(&param)
{
    m_d = &data;
    data.m_checker->resetTickCheck();
}

HplcZkysParseCommonPacket::~HplcZkysParseCommonPacket()
{

}

void HplcZkysParseCommonPacket::parse()
{
//    qDebug() << m_d->m_rxPacket.timestamp << m_d->m_rxPacket.buffer;

    HplcZkysProtocolCommonData *m_d = static_cast<HplcZkysProtocolCommonData*>(this->m_d);

    {
        quint8 address = m_d->m_rxPacket.buffer.at(0);
        quint8 pfc = m_d->m_rxPacket.buffer.at(1);
        char *data = m_d->m_rxPacket.buffer.data() + 2;
        int len = m_d->m_rxPacket.buffer.size() - 4;
        uint8_t isSet = pfc & 0x80;
        pfc &= 0x7F;

        if (address == GLOBAL_ADDRESS) // 广播
        {
            if (pfc == PFC_GLOBAL_DEVICE_ADDRESS) // 广播只对设备地址读写有效
            {
                m_d->m_checker->resetTickCheck();

                if (isSet)
                {
                    m_d->m_address = data[0];
                }
                else
                {
                    getSender()->setDeviceAddress(m_d->m_address);
                }
            }
            return;
        }

        // 地址不匹配则退出
        if (address != m_d->m_address)
        {
            return;
        }

        m_d->m_checker->resetTickCheck();

        if (isSet)
            parseSet(pfc, data, len);
        else
            parseGet(pfc, data, len);
    }
}

void HplcZkysParseCommonPacket::parseSet(quint8 pfc, char *data, int len)
{
    switch (pfc)
    {
    case PFC_GLOBAL_DEVICE_ADDRESS:
    {
        m_param->devAddress = data[0];

        QVariant var;
        var.setValue(m_param->devAddress);
        emit parseCompleted(hplc::CommonCmdID_SetDeviceAddress, var);
    }
        break;
    case PFC_GLOBAL_SOFTWARE_VERSION:
    {
        QString version = QString(data);
        m_param->softwareVersion = version;

        QVariant var;
        var.setValue(m_param->softwareVersion);
        emit parseCompleted(hplc::CommonCmdID_SetSoftwareVersion, var);
    }
        break;
    case PFC_GLOBAL_HARDWARE_VERSION:
    {
        QString version = QString(data);
        m_param->hardwareVersion = version;

        QVariant var;
        var.setValue(m_param->hardwareVersion);
        emit parseCompleted(hplc::CommonCmdID_SetHardwareVersion, var);
    }
        break;
    case PFC_GLOBAL_PRODUCT_DATE:
    {
        QString str = QString(data);
        m_param->productDate = str;

        QVariant var;
        var.setValue(m_param->productDate);
        emit parseCompleted(hplc::CommonCmdID_SetProductDate, var);
    }
        break;
    case PFC_GLOBAL_SERIAL_NUMBER:
    {
        QString str = QString(data);
        m_param->serialNumber = str;

        QVariant var;
        var.setValue(m_param->serialNumber);
        emit parseCompleted(hplc::CommonCmdID_SetSerialNumber, var);
    }
        break;
    case PFC_GLOBAL_MODEL:
    {
        QString str = QString(data);
        m_param->modelString = str;

        QVariant var;
        var.setValue(m_param->modelString);
        emit parseCompleted(hplc::CommonCmdID_SetModel, var);
    }
        break;
    case PFC_GLOBAL_USED_TIME:
    {
        quint32 time = PTR2U32(data);
        m_param->usedTime = time;

        QVariant var;
        var.setValue(m_param->usedTime);
        emit parseCompleted(hplc::CommonCmdID_SetUsedTime, var);
    }
        break;
    case PFC_GLOBAL_SYNC_TIME:
    {
        quint32 time = PTR2U32(data);
        m_param->syncTime = time;

        QVariant var;
        var.setValue(m_param->syncTime);
        emit parseCompleted(hplc::CommonCmdID_SetSyncTime, var);
    }
        break;
    case PFC_GLOBAL_INPUT:
    {
        if (m_param->input.size() < data[0] + 1)
            break;
        m_param->input[data[0]] = data[1];

        hplc::Input in;
        in.number = data[0];
        in.level = data[1];
        QVariant var;
        var.setValue(in);
        emit parseCompleted(hplc::CommonCmdID_SetInput, var);
    }
        break;
    case PFC_GLOBAL_OUTPUT:
    {
        if (m_param->output.size() < data[0] + 1)
            break;
        m_param->output[data[0]] = data[1];

        hplc::Output out;
        out.number = data[0];
        out.level = data[1];
        QVariant var;
        var.setValue(out);
        emit parseCompleted(hplc::CommonCmdID_SetOutput, var);
    }
        break;
    case PFC_GLOBAL_TICK:
    {

    }
        break;
    case PFC_GLOBAL_TICK_PERIOD:
    {
        m_param->tickPeriod = data[0];

        QVariant var;
        var.setValue(m_param->tickPeriod);
        emit parseCompleted(hplc::CommonCmdID_SetTickPeriod, var);
    }
        break;
    case PFC_GLOBAL_REPLY:
    {
        HplcZkysProtocolCommonData *m_d = static_cast<HplcZkysProtocolCommonData*>(this->m_d);
        m_d->m_checker->replyCheck(data);
    }
        break;
    case PFC_GLOBAL_ERROR:
    {
        m_param->errorCode = data[0];

        QVariant var;
        var.setValue(m_param->errorCode);
        emit parseCompleted(hplc::CommonCmdID_SetSystemError, var);
    }
        break;
    case PFC_GLOBAL_ERROR_UPLOAD_FREQ:
    {
        m_param->errorCodeUploadFreq = data[0];

        QVariant var;
        var.setValue(m_param->errorCodeUploadFreq);
        emit parseCompleted(hplc::CommonCmdID_SetSystemErrorUploadFreq, var);
    }
        break;
    case PFC_GLOBAL_EXT_SYSTEM:
    {
        HplcZkysProtocolCommonData *m_d = static_cast<HplcZkysProtocolCommonData*>(this->m_d);
        m_d->m_commonSystemParser->parseSet(data[0], data + 1, len - 1);
    }
        break;
    case PFC_GLOBAL_EXT_USER:
        break;
    default:
        qDebug() << "error pfc";
        break;
    }
}

void HplcZkysParseCommonPacket::parseGet(quint8 pfc, char *data, int len)
{
    HplcZkysSendCommonPacket *sender = static_cast<HplcZkysSendCommonPacket*>(m_d->m_sender);
    switch (pfc)
    {
    case PFC_GLOBAL_DEVICE_ADDRESS:
        sender->getDeviceAddress();
        break;
    case PFC_GLOBAL_SOFTWARE_VERSION:
        sender->getSoftwareVersion();
        break;
    case PFC_GLOBAL_HARDWARE_VERSION:
        sender->getHardwareVersion();
        break;
    case PFC_GLOBAL_PRODUCT_DATE:
        sender->getProductDate();
        break;
    case PFC_GLOBAL_SERIAL_NUMBER:
        sender->getSerialNumber();
        break;
    case PFC_GLOBAL_MODEL:
        sender->getModel();
        break;
    case PFC_GLOBAL_USED_TIME:
        sender->getUsedTime();
        break;
    case PFC_GLOBAL_SYNC_TIME:
        sender->getSyncTime();
        break;
    case PFC_GLOBAL_INPUT:
        sender->getInput(data[0]);
        break;
    case PFC_GLOBAL_OUTPUT:
        sender->getOutput(data[0]);
        break;
    case PFC_GLOBAL_TICK:
        break;
    case PFC_GLOBAL_TICK_PERIOD:
        sender->getTickPeriod();
        break;
    case PFC_GLOBAL_REPLY:
        qWarning() << "Can not read reply";
        break;
    case PFC_GLOBAL_ERROR:
        sender->getSystemError();
        break;
    case PFC_GLOBAL_ERROR_UPLOAD_FREQ:
        sender->getSystemErrorUploadFreq();
        break;
    case PFC_GLOBAL_EXT_SYSTEM:
    {
        HplcZkysProtocolCommonData *m_d = static_cast<HplcZkysProtocolCommonData*>(this->m_d);
        m_d->m_commonSystemParser->parseGet(data[0], data + 1, len - 1);
    }
        break;
    case PFC_GLOBAL_EXT_USER:
        break;
    default:
        qDebug() << "error pfc";
        break;
    }
}

HplcZkysSendCommonPacket *HplcZkysParseCommonPacket::getSender()
{
    return static_cast<HplcZkysSendCommonPacket*>(m_d->m_sender);
}

} // zkys
} // hplc
